﻿using System;
using System.Collections.Generic;
using System.Linq;
using Pfz.Factoring;
using System.Windows;

namespace Pfz.WpfControls
{
	/// <summary>
	/// Class that controls how all searches are shown in the application.
	/// </summary>
	public static class Searcher
	{
		static Searcher()
		{
			Searching = (args) =>
			{
				var window = new WindowWithResult();
				window.Title = "Searcher";

				args.Searcher.FillDefaultParameters(args.DefaultParameters);
				args.Searcher.MustAllowMultiSelect = args.Searcher.MustAllowMultiSelect;
				window.Content = args.Searcher;

				using
				(
					new ResultSetter
					(
						(result) => 
						{
							window.Result = result;
							window.DialogResult = true;
						}
					)
				)
				{
					window.ShowDialog();
				}

				return (ICollection<object>)window.Result;
			};
		}

		/// <summary>
		/// Searches for one or more records.
		/// </summary>
		public static ICollection<object> Search(Type dataType, object defaultParameters, bool allowMultiSelect)
		{
			var handler = _threadSearching;
			if (handler == null)
			{
				handler = Searching;

				if (handler == null)
					throw new InvalidOperationException("The Searching and ThreadSearching handlers are not set.");
			}

			var factory = Factories<ISearcher>.CreateFactory(dataType);
			var control = factory.Create();

			SearcherArgs args = new SearcherArgs();
			args.Searcher = control;
			args.DefaultParameters = defaultParameters;
			var result = handler(args);
			return result;
		}

		/// <summary>
		/// Searches a single record and wait until one is selected.
		/// </summary>
		public static T SearchSingle<T>(object defaultParameters=null)
		{
			return (T)SearchSingle(typeof(T), defaultParameters);
		}

		/// <summary>
		/// Searches a single record and wait until one is selected.
		/// </summary>
		public static object SearchSingle(Type dataType, object defaultParameters=null)
		{
			var result = Search(dataType, defaultParameters, false);

			if (result == null)
				return null;

			return result.SingleOrDefault();
		}

		/// <summary>
		/// Searches one or more results.
		/// </summary>
		public static ICollection<object> SearchMultiple(Type dataType, object defaultParameters=null)
		{
			return Search(dataType, defaultParameters, true);
		}

		/// <summary>
		/// Gets or sets the function used to show searchers in the entire application.
		/// </summary>
		public static Func<SearcherArgs, ICollection<object>> Searching { get; set; }

		[ThreadStatic]
		internal static Func<SearcherArgs, ICollection<object>> _threadSearching;
	}
}
